/// 地图
module factories.map;

import factories.tile;
import factories.util;

/// 图块大小
enum chunkSize = 0.12;

/// 最大地图大小
version (unittest)
	enum mapWidth = 16;
else
	enum mapWidth = 64;

/// 地图
extern (C) export Tile[mapWidth * mapWidth] map;

void genMap(uint x, uint y, uint width, uint height, float up, float left, float down, float right) {
	import std.algorithm : max, min;

	uint hw = width >> 1, hv = height >> 1;
	if (width > 1 || height > 1) {
		auto f = (rand() - .5) * (hw + hv) * chunkSize,
		c = (up + left + down + right) / 4 + f;
		c = c > 1 ? 1 : 0 > c ? 0 : c;
		const ul = (up + left) / 2,
		ld = (left + down) / 2,
		dr = (down + right) / 2,
		ru = (right + up) / 2;
		genMap(x, y, hw, hv, up, ul, c, ru);
		genMap(x + hw, y, width - hw, hv, ul, left, ld, c);
		genMap(x + hw, y + hv, width - hw, height - hv, c, ld, down, dr);
		genMap(x, y + hv, hw, height - hv, ru, c, dr, right);
	} else {
		// 海拔
		const alt = (up + left + down + right) / 4;
		assert(alt >= 0 && alt <= 1);

		const h = max(max(up, left), max(down, right)) - min(min(up, left), min(down, right));
		const grad = cast(int)(h * 32);
		// 块索引
		const i = y * mapWidth + x;
		map[i].terrain = getTerrain(cast(int)(alt * 15) - 3, grad > 7 ? 2 : grad > 4);
		map[i].temperature = cast(uint)(saturate(octavedNoise(x - down, y, 0.3, 0.5)) * 15);
		map[i].humidity = cast(uint)(saturate(octavedNoise(x, y + left, 0.3, 0.7)) * 15);
	}
}

/**
 * 生成地图，seed为种子
 */
void initMap() {
	genMap(0, 0, mapWidth, mapWidth, rand(), rand(), rand(), rand());
}

/// 获取地形，alt=海拔，grad=坡度(deg)
Terrain getTerrain(int alt, int grad) {
	if (alt > 7) {
		if (grad == 0)
			return Terrain.highland;
		return Terrain.peak;
	}
	if (alt == -1)
		return Terrain.shallows;
	if (alt < -1)
		return Terrain.deepwater;
	if (alt == 0 && grad == 0)
		return Terrain.sand;
	if (alt > 0 && grad == 0)
		return Terrain.lowland;
	if (grad == 1)
		return Terrain.mountain;
	if (alt > 1 && grad > 1)
		return Terrain.cliff;
	return Terrain.lowland;
}
